package org.gongliang.common.scan;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.gongliang.common.annotation.KLog;
import org.gongliang.common.base.Result;
import org.gongliang.common.exception.BussinessException;
import org.gongliang.common.exception.ExceptionEnum;
import org.gongliang.common.exception.ParamException;
import org.gongliang.common.shiro.ShiroUser;
import org.gongliang.entity.sys.Log;
import org.gongliang.kit.str.BeanKit;
import org.gongliang.kit.web.ShiroKit;
import org.gongliang.kit.web.UserAgentKit;
import org.gongliang.kit.web.WebKit;
import org.gongliang.task.TaskLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;

/**
 * 
 * @Description 全局异常处理
 * @author 龚亮
 * @date 2017年3月30日 下午3:34:16
 */
@Component
public class KExceptionHandler implements HandlerExceptionResolver {

	public static final Logger logger = LoggerFactory
			.getLogger(KExceptionHandler.class);

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception exception) {
		logger.error("异常信息:" + ExceptionUtils.getStackTrace(exception));
		Class<? extends Exception> cls = exception.getClass();
		FastJsonJsonView jsonView = new FastJsonJsonView();
		ModelAndView mv = new ModelAndView();
		Result result = Result.error();
		if (cls.isAssignableFrom(BussinessException.class)) {
			// 逻辑异常
			Integer resCode = ((BussinessException) exception).getErrCode();
			String resMsg = ((BussinessException) exception).getErrMsg();
			result.setResCode(resCode);
			result.setResMsg(resMsg);
		} else if (cls.isAssignableFrom(ParamException.class)) {
			Integer resCode = ((ParamException) exception).getErrCode();
			String resMsg = ((ParamException) exception).getErrMsg();
			result.setResCode(resCode);
			result.setResMsg(resMsg);
		} else if (cls.isAssignableFrom(UnauthorizedException.class)) {
			result.setResCode(ExceptionEnum.NOT_PERMISSION.getResCode());
			result.setResMsg(ExceptionEnum.NOT_PERMISSION.getResMsg());
		} else {
			// 其它异常
			result.setResCode(ExceptionEnum.SERVER_ERROR.getResCode());
			result.setResMsg(ExceptionEnum.SERVER_ERROR.getResMsg());
		}
		if (handler instanceof HandlerMethod) {
			HandlerMethod method = (HandlerMethod) handler;
			if (method.hasMethodAnnotation(ResponseBody.class)
					|| method.getBeanType().isAnnotationPresent(RestController.class)
					|| WebKit.isAjaxRequest(request)) {
				jsonView.setAttributesMap(BeanKit.beanToMap(result));
				mv.setView(jsonView);
			} else {
				if (cls.isAssignableFrom(UnauthorizedException.class)) {
					mv.setViewName("redirect:/public/error/unauthc.html");
				} else {
					mv.setViewName("redirect:/public/error/500.html");
				}
			}
			if (method.hasMethodAnnotation(KLog.class)) {
				saveLog(request, exception, method.getMethodAnnotation(KLog.class));
			}
		}
		return mv;
	}

	public void saveLog(HttpServletRequest request, Exception exception, KLog kLog) {
		Log log = new Log();
		log.setIp(WebKit.getIpAddr(request));
		log.setCreateDate(new java.util.Date());
		ShiroUser user = ShiroKit.getLoginUser();
		if (user != null) {
			log.setCreator(user.getId());
		}
		log.setUserAgent(UserAgentKit.getUserAgent(request).toString());
		log.setReqUrl(request.getRequestURI());
		Map<String, Object> reqParams = WebKit.getParams(request);
		if (reqParams.containsKey("password")) {
			reqParams.put("password", "******");
		}
		if (reqParams.containsKey("newPassword")) {
			reqParams.put("newPassword", "******");
		}
		log.setReqParam(JSON.toJSONString(reqParams));
		log.setReqMethod(request.getMethod());
		if (exception != null) {
			log.setException(ExceptionUtils.getStackTrace(exception));
			log.setReqOk(false);
		} else {
			log.setReqOk(true);
		}
		log.setRemark(kLog.value());
		logger.debug("日志记录:" + JSON.toJSONString(log));
		TaskLog.getSingleton().add(log);
	}

}
